#include "PlatformProfileImpl.h"

namespace ecarx::platform::profile {

#define PROFILE_DIR_PATH "/data/vendor/vehicle_hal/"
#define CREATED_PROFILE_IDS_KEY "created_profile_ids"
#define ACTIVE_PROFILE_ID "active_profile_id"

PlatformProfileImpl::PlatformProfileImpl()
    : mPath(PROFILE_DIR_PATH), mAuxiliary(std::make_shared<ProfileAuxiliary>(PROFILE_DIR_PATH)) {
    // 加载已经创建好的profileId标识 12和13比较特殊 默认创建
    mCreatedProfileIds = mAuxiliary->getInt32Array(CREATED_PROFILE_IDS_KEY, {12, 13});
    for (int profileId : mCreatedProfileIds) {
        mProfiles.insert_or_assign(profileId, std::make_unique<Profile>(mPath.c_str(), profileId));
    }
    // 默认加载当前的profile为游客即profileId等于13
    int activeProfileId = mAuxiliary->getInt32(ACTIVE_PROFILE_ID, 13);
    if (!isCreated(activeProfileId)) {
        mCreatedProfileIds.push_back(activeProfileId);
        mProfiles.insert_or_assign(activeProfileId, std::make_unique<Profile>(mPath.c_str(), activeProfileId));
    }
    mActiveProfile = mProfiles[activeProfileId].get();
    // 保存created_profile_ids和active_profile_id信息
    mAuxiliary->setInt32(ACTIVE_PROFILE_ID, mActiveProfile->getProfileId());
    mAuxiliary->setInt32Array(CREATED_PROFILE_IDS_KEY, mCreatedProfileIds);
    mAuxiliary->save();
}

void PlatformProfileImpl::onInit() {
    //创建期间 这里确定当前的Profile是谁
    notifySwicthProfile(nullptr, mActiveProfile);
}

bool PlatformProfileImpl::createProfile(int32_t newProfileId, int32_t cloneProfileId) {
    auto iter = mProfiles.find(newProfileId);
    if (iter != mProfiles.end() || isCreated(newProfileId)) {
        return false;
    }
    if (cloneProfileId == 0) {
        mProfiles.insert_or_assign(newProfileId,
            std::make_unique<Profile>(mPath.c_str(), newProfileId));
        mCreatedProfileIds.push_back(newProfileId);
        mAuxiliary->setInt32Array(CREATED_PROFILE_IDS_KEY, mCreatedProfileIds);
        mAuxiliary->save();
        return true;
    } else {
        auto cloneItr = mProfiles.find(cloneProfileId);
        if (cloneItr != mProfiles.end()) {
            mProfiles.insert_or_assign(newProfileId, cloneItr->second->cloneTo(newProfileId));
            mCreatedProfileIds.push_back(newProfileId);
            mAuxiliary->setInt32Array(CREATED_PROFILE_IDS_KEY, mCreatedProfileIds);
            mAuxiliary->save();
            return true;
        }
    }
    return false;
}

std::shared_ptr<ProfileAuxiliary> PlatformProfileImpl::getAuxiliary() {
    return mAuxiliary;
}

std::vector<int32_t> PlatformProfileImpl::getCreatedProfileIds() {
    return mCreatedProfileIds;
}

bool PlatformProfileImpl::isCreated(int32_t profileId) {
    for (auto pid : mCreatedProfileIds) {
        if (pid == profileId) {
            return true;
        }
    }
    return false;
}

bool PlatformProfileImpl::deleteProfile(int32_t profileId) {
    if (profileId == 12 || profileId == 13) {
        return false;
    }
    if (isCreated(profileId)) {
        bool fileDelete = false;
        auto itr = mProfiles.find(profileId);
        if (itr != mProfiles.end()) {
            fileDelete = itr->second->deleteFile();
            if (mActiveProfile != nullptr && profileId == mActiveProfile->getProfileId()) {
                mActiveProfile = nullptr;
            }
            mProfiles.erase(itr);
        } else {
            Profile profile(mPath.c_str(), profileId);
            fileDelete = profile.deleteFile();
        }
        if (fileDelete) {
            for (auto it = mCreatedProfileIds.begin(); it != mCreatedProfileIds.end();) {
                if ((*it) == profileId) {
                    it = mCreatedProfileIds.erase(it);
                } else {
                    it++;
                }
            }
            mAuxiliary->setInt32Array(CREATED_PROFILE_IDS_KEY, mCreatedProfileIds);
            mAuxiliary->save();
        }
        return fileDelete;
    }
    return false;
}

bool PlatformProfileImpl::activeProfile(int32_t profileId) {
    if (mActiveProfile != nullptr && mActiveProfile->getProfileId() == profileId) {
        return false;
    }
    mAuxiliary->setInt32(ACTIVE_PROFILE_ID, profileId);
    bool switchProfile = false;
    auto itr = mProfiles.find(profileId);
    if (itr == mProfiles.end()) {
        if (isCreated(profileId)) {
            itr = mProfiles.insert_or_assign(profileId, std::make_unique<Profile>(mPath.c_str(), profileId)).first;
            switchProfile = true;
        }
    } else {
        switchProfile = true;
    }
    if (switchProfile && itr != mProfiles.end()) {
        Profile* last = nullptr;
        if (mActiveProfile != nullptr) {
            last = mActiveProfile;
            mActiveProfile->save();
        }
        mActiveProfile = itr->second.get();
        mAuxiliary->save();
        for (auto listener : mListeners) {
            listener->onSwitchProfile(last, mActiveProfile);
        }
    }
    return switchProfile && itr != mProfiles.end();
}

Profile* PlatformProfileImpl::getCurrentProfile() {
    return mActiveProfile;
}

void PlatformProfileImpl::addProfileListener(ProfileListener* listener) {
    mListeners.insert(listener);
}

void PlatformProfileImpl::removeProfileListener(ProfileListener* listener) {
    for (auto it = mListeners.begin(); it != mListeners.end(); it++) {
        if ((*it) == listener) {
            mListeners.erase(it);
            break;
        }
    }
}

void PlatformProfileImpl::notifySwicthProfile(Profile* last, Profile* current) {
    for (auto listener : mListeners) {
        listener->onSwitchProfile(last, current);
    }
}

bool PlatformProfileImpl::deleteCurrentProfilePreference(int32_t perferenceId) {
    if (mActiveProfile == nullptr) {
        return false;
    }

    return mActiveProfile->deletePreference(perferenceId);
}

bool PlatformProfileImpl::activeCurrentProfilePreference(int32_t perferenceId) {
    if (mActiveProfile == nullptr) {
        return false;
    }

    auto preference = mActiveProfile->getCurrentPreference();
    if (preference->getPreferenceId() == perferenceId) {
        return true;
    }
    bool ret = mActiveProfile->activePreference(perferenceId);
    if (ret) {
        for (auto listener : mListeners) {
            listener->onSwitchProfile(mActiveProfile, mActiveProfile);
        }
    }
    return ret;

}

}  // namespace ecarx::platform::profile
